概览
Prisma 使用 GraphQL Schema Definition Language
定义数据模型.数据模型可以写在一个或多个.graphql
文件中.在内部它是 Prisma 生成实际数据库 schema 的基础.如果只使用单个的定义文件,可以被称为datamodel.graphql
.
.graphql
文件需要在prisma.yml
中声明. 例如:
1 | datamodel: |
如果是单个文件:
1 | datamodel:datamodel.graphql |
data model 是 基于Prisma服务的 GraphQL API 的基础. Prisma会以此生成一套强有力的 Graphql Schema(被称为 Prisma data schema),为 data model 定义了全部的 CRUD 操作.
实例
一个简单的datamodel.graphql
文件:
1 | type Tweet { |
实例展示了一些data model 的重要概念:
- 三个类型
Tweet
,User
,Location
被映射到数据库的表中 User
,Tweet
之间是双向关系Tweet
到Location
是单向关系- 除了
User
的name
字段,所有的字段都是必须的(用!表示) id
,createdAt
,updateAt
字段由 Prisma 管理,在 GraphQL API 中只读
创建和更新 datamodel 和修改文本文件一样简单.一旦 datamodel 的修改达到你的需求,可以执行prisma deploy
命令 :
1 | $ prisma deploy |
构建 data model 模块
有几种可以使用的模块用于描述 data model
Types
包含fields,用于把类似的实体分组. 每个data model 中的 type 都被映射到数据库的表和 CRUD操作,然后添加的 graphQL 的 schema 中Relations
描述 typee 之间的关系Interfaces
属于抽象 types,包含了一组特定的字段, type在实现时必须要遵循. 现在 interface 还不能由用户定义.但是已经有这样的需求.- 特定的
directives
指令,包含不同的使用用例, 例如 type 约束或者是级联删除的行为.
接下里的内容就是描述这些构建块的具体细节问题
Prisma 的 database 和 data model
刚开使用 GraphQL和 Prisma时, .graphql
文件的数量会让你不是所措.然而理解每个文件扮演的角色又是很关键的问题.
总体上讲,一个graphql
文件可以包含下面的内容:
- GraphQL 的操作(例如 query, mutate或者 subscriptions)
- 使用 SDL 定义的 GraphQL type
如果要区分 Prisma database schema 和 data model的话,只有后者是有关联的!
现在这一很重要data model 并不是实际的 GraphQL schema
,虽然也是用 SDL定义的,但是缺少 root types,所以不能生成实际的 API 操作符! Prisma 只是使用 data model作为一个硬工具表达一下具体的 data model 的外观.
正如上面提到的, Prisma 会生成实际的 GraphQL schema,包含query
,mutation
,subscription
三种 root type. 生成的 prisma.graphql
文件被称为 Prisma database schema .注意了,一定不要修改这个文件.这是系统自己生成的.
作为实例,看看一个最简单的 data model:
datamodel graphql
1 | type User { |
如果部署了 Prisma 的服务, Prisma 将会生成服务所需的一些 API:
prisma.graphql
1 | type Query { |
其实在生成的 Graphql server 中还有一个
.graphql
文件, 这个文件被称为 application shema. 这里定义的 API是实际暴露给最终用户的
. Prisma 的 API 就作为 “query egine”来实际执行操作.
所以,一个 基于PRISMA的Graphql server实际包含两个 API.可以认为是服务的两个数据层:
- Aplication layer: 定义客户端可以使用的操作
- Database layer: 定义 Prisma database 的服务
Object types
object type(简称为 type)定义了实现data model 的实际组成部分. 用于代表应用主域的实体.
如果你很熟悉 SQL databases,可以把 type 看成是 关系型数据库的 table,一个 type 有一个名字,一个或者多个字段.
type的实例称为 node,这个术语指的是 data graph 中的 node. 在 data model 中定义的每个 type和 Prisma生成的 database schema 很类似.
定义一个 object type
用type
关键字定义一个object type
1 | type Article { |
对于使用@unique
限定的字段可以借此查询对应的 node.
例如可以返回拥有此 email 的用户节点:
1 | query { |
后续还有其他的限定条件加入
Default Value
可以为标量设定默认值. @default
指令
1 | type Story { |
一定要用双引号,即使不是字符串
System fields
三个字段id
,createdAt
,updatedAT
有特殊的意义. 在 datamodel 中是可选,但是在底层的数据库中会一直存在.
除非要是导入的数据, 否则, 这三个值在 graphql API 中是只读的.
Relations
relation 定义了连接两个 type 的语法. 两个类型通过 relation fields 连接在一起.如果 relation 可能会混淆的时候,要使用@relation
来区分开
连接自身的字段也可以
Required relations
@relation
directive
有两个参数
name
: 用于识别 relation.onDelete
:用于定义删除行为:SET_NULL
(default):设定 related node 为null
CASCADE
:删除 related nodes.
实例:
1 | type User { |
上面例子的删除行为:
- 当
User
node被删除以后, 与之有关的Story
node 也被删除 - 当
Story
node被删除,只会从User
的stories
列表中删除
省略@relation
指令
当两个 type 不会发生歧义的时候,可以不用写这个指令
1 | type User { |
- 当
User
删除掉,author
中所有的相关Story
都会被设为null
.如果 author 被设定为 required,操作就会引发错误 - 当一个
Story
被删除掉以后,只会从User
node list 中删除
在@relation
指令中使用name
参数
1 | type User { |
在@relation
指令中使用onDelete
参数
1 | type User { |
看看三个不同的类型:
User
node 被删除- 所有的
Comment
nodes 被删除 Blog
node 也被删除
- 所有的
- 当
Blog
node 被删除,- 所有相关的
Comment
nodes被删除 - 拥有
blog
字段的User
node 被设置为空
- 所有相关的
- 当
Comment
node 被删除- 相关的
Blog
node会继续存在,Comments
会从comment
list 中删掉 - 相关的
User
会一直存在,Comment
node会从comments
list 中删掉
- 相关的
为 relations 生成 API 操作
relation queries
会跨 types查询数据或者聚合 relationnest mutations
跨 types, create,connect,update upsert和 delete nodesrelation subscription
改变 relation时获取通知
GraphQL 指令
临时性指令
renaming a type or field
@rename(oldName:String!)
1 | # renaming the `Post` type to `Story`, and its `text` field to `content` |